#ifndef _IO_BASE_H_
#define _IO_BASE_H_

#include <stdint.h>
#include "io_sock.h"
#include "list.h"
#include "io_tools.h"
#include "buffer.h"
#include <sys/signalfd.h>
#include <signal.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct io_base io_base_t;
typedef struct io_client io_client_t;
typedef struct io_event io_event_t;
typedef struct io_ctrl_msg io_ctrl_msg_t;


/******************************************************************************
 *                         io base
 *****************************************************************************/
typedef struct io_base_conf {
    char name[16];
    char ip[16];
    uint16_t port;
	sigset_t *mask;
}io_base_conf_t;

io_base_t *io_base_new(io_base_conf_t *conf);
void io_base_destroy(io_base_t **p_self);
int io_base_accept(io_base_t *self, sock_t *s);
int io_base_signo(io_base_t *self);
int io_base_loop(io_base_t *self, int timeout);
int io_base_stop(io_base_t *self);
//uint32_t io_base_ev_nums(io_base_t *self);
struct dl_list *io_base_ev_list(io_base_t *self);


/*****************************************************************************
 *                         io event
 ****************************************************************************/
#define IO_EVENT_UNKNOW     0x0
#define IO_EVENT_ACCEPT     0x1
#define IO_EVENT_READ       0x2
#define IO_EVENT_WRITE      0x4
#define IO_EVENT_ERROR      0x8
#define IO_EVENT_CLOSE      0x10
#define IO_EVENT_SIGNAL		0x20
#define IO_EVENT_CTRL       0x40

struct io_event {
    struct dl_list head;
    uint16_t event;
    void *ctx;
};

typedef struct io_event_iterator {
    struct dl_list evs;
	io_base_t *base;
	io_event_t io_ev;
}io_event_iterator_t;

void io_event_iterator_init(io_base_t *self, io_event_iterator_t *it);
io_event_t *io_events_next(io_event_iterator_t *it);
void io_event_iterator_term(io_event_iterator_t *it);

/*****************************************************************************
 *                      io client
 ****************************************************************************/
#define IN_BUF_SIZE     512

struct io_client {
    struct dl_list head;
    io_base_t *base;
    sock_t sock;
    
    uint16_t in_len;
    uint8_t in_buf[IN_BUF_SIZE];
    buffer_t out_buf;
    
    int event;
    io_event_t io_ev;
    uint8_t ref;
};

int io_client_init(io_client_t *cli, sock_t *s, io_base_t *serv);
void io_client_term(io_client_t *cli);
int io_client_write(io_client_t *self, void *data, size_t len);

static inline uint8_t io_client_get(io_client_t *self)
{
    self->ref++;
    return self->ref;
}

uint8_t io_client_put(io_client_t *self);

static inline io_client_t *io_client_new(sock_t *s, io_base_t *base)
{
	io_client_t *self = (io_client_t *)MALLOC(sizeof(io_client_t));
	if (self) {
		if (io_client_init(self, s, base) < 0)
			safe_free(self);
	}

	return self;
}

static inline void io_client_destroy(io_client_t **p_self)
{
	if (p_self && *p_self) {
		io_client_t *self = *p_self;
		if (!io_client_put(self))
			safe_free(*p_self);
	}
}

/*****************************************************************************
 *                   io control message
 ****************************************************************************/
struct io_ctrl_msg {
    uint8_t sync;
    uint8_t id;
    uint16_t len;
	union {
		int sig;
		uint8_t data[256];
	}u;
};

#define IO_BASE_MSG_SYNC        0xA5
#define IO_BASE_MSG_ID_EXIT     0x1
#define IO_BASE_MSG_ID_SIG		0x2


#ifdef __cplusplus
}
#endif

#endif
